www.gusucode.com > VC++ 实现图像中的文字提取-源码程序 > VC++ 实现图像中的文字提取-源码程序/code/图像中文字提取的程序/ImageAnalysis.cpp

    //Download by http://www.NewXing.com
#include "stdafx.h"
#include "GlobalApi.h"
#include "Cdib.h"

#include <io.h>
#include <errno.h>

#include <math.h>
#include <direct.h>



 /*
  说明:
   该函数将消去图象中面积小于或大于阈值的区域,实现文字提取*/
 
 

BOOL DIBHOLENUMBER(CDib *pDib)
{
	// 指向源图像的指针
	BYTE *	lpSrc;

	//图象的宽度和高度
	LONG    lWidth;
	LONG    lHeight;

	// 图像每行的字节数
	LONG	lLineBytes;
	
	//得到图象的宽度和高度
	CSize   SizeDim;
	SizeDim = pDib->GetDimensions();
	lWidth  = SizeDim.cx;
	lHeight = SizeDim.cy;	
	
	//得到实际的Dib图象存储大小
	CSize   SizeRealDim;
	SizeRealDim = pDib->GetDibSaveDim();

	// 计算图像每行的字节数
	lLineBytes = SizeRealDim.cx;
	
	//图像数据的指针
	LPBYTE  lpDIBBits = pDib->m_lpImage;

	// 循环变量
	int i, j, s, n;

	// 空穴的数目以及面积阈值
	int nHoleNum, nMinArea,nMaxArea;

	int nBlackPix, temp;

	// 正向和反响传播标志
	int nDir1,nDir2;

	// 用来存储的一位数组
	int *pnBinary;

	pnBinary =new int[lHeight*lLineBytes];

	// 定义阈值的大小
	nMinArea = 130; 
	nMaxArea = 700;

	// 将图象二值化
	for (j = 0; j < lHeight; j++)
	{
		for(i = 0; i < lWidth; i++)
		{
			// 指向源图像倒数第j行,第i个象素的指针			
			lpSrc = (unsigned char *)lpDIBBits + lLineBytes * j + i;

			// 白色象素为背景,存成0
			if(*lpSrc > 200)
			{
				pnBinary[lLineBytes * j + i] = 0;
			}
			// 黑象素存成-1
			else
			{
				pnBinary[lLineBytes * j + i] = -1;
			}
		}		
	}
	
	// 空穴数赋初值
	nHoleNum = 1;
	
	do
	{
		s=0;
		
		// 寻找每个空穴的初始象素值 
		for (j = 1; j < lHeight - 1; j++)
		{
			for(i = 1; i < lWidth - 1; i++)
			{
				// 找到初始象素
				if(pnBinary[lLineBytes * j + i] == -1)
				{
					s = 1;
					// 将象素值改成当前的空穴数值
					pnBinary[lLineBytes * j + i] = nHoleNum;
					
					// 跳出循环
					j = lHeight;			
					i = lLineBytes;
				}
			}
		}

		//没有初始象素,跳出循环
		if(s == 0)
			break;
		else
		{
			do
			{
				// 正向和反响系数赋初值0
				nDir1 = 0;
				nDir2 = 0;

				// 正向扫描
			for (j = 1; j < lHeight-1; j++)
			{
				for(i = 1; i < lWidth-1; i++)
				{
					nBlackPix = pnBinary[lLineBytes * j + i];
						
					// 如果象素已经被扫描,或者是背景色,进行下一个循环
					 if(nBlackPix != -1)
							continue;

				// 如果上侧或者左侧的象素值已经被扫描,且属于当前的空穴,当前的象素值
				// 改成空穴的数值
						nBlackPix=pnBinary[lLineBytes * (j-1) + i];
						if(nBlackPix == nHoleNum)
						{
							pnBinary[lLineBytes * j + i] = nHoleNum;
							nDir1 = 1;
							
							continue;
						}

						nBlackPix =pnBinary[lLineBytes * j + i - 1];						
						if(nBlackPix == nHoleNum)
						{
							pnBinary[lLineBytes * j + i] = nHoleNum;
							nDir1 = 1;
						}
					
					}
				}

				// 正向象素全部被扫描,跳出循环
				if(nDir1 == 0)
					break;

				// 反向扫描
				for (j = lHeight-2; j >= 1 ; j--)
				{
					for(i = lWidth-2; i >= 1 ; i--)
					{
						nBlackPix = pnBinary[lLineBytes * j + i];						
						
						// 如果象素已经被扫描,或者是背景色,进行下一个循环
						if(nBlackPix != -1)
							continue;

						// 如果下侧或者右侧的象素值已经被扫描,且属于当前的空穴,当前的象素值
						// 改成空穴的数值
						nBlackPix=pnBinary[lLineBytes * (j+1) + i];
						if(nBlackPix == nHoleNum)
						{
							pnBinary[lLineBytes * j + i] = nHoleNum;
							nDir2 = 1;
							
							continue;
						}

						nBlackPix =pnBinary[lLineBytes * j + i + 1];						
						if(nBlackPix == nHoleNum)
						{
							pnBinary[lLineBytes * j + i] = nHoleNum;
							nDir2 = 1;
						}
					}
				}

				if(nDir2 == 0)
					break;
			}
			while(1);
		}
		// 空穴数增加
		nHoleNum++;
	}
	while(1);

	nHoleNum -- ;

	// 寻找面积小于或大于阈值的区域
	for(n = 1; n <= nHoleNum; n++)
	{
		s = 0;
		
		for (j = 0; j < lHeight - 1; j++)
		{
			for(i = 0; i < lWidth - 1; i++)
			{
				nBlackPix =pnBinary[lLineBytes * j + i];
				
				if(nBlackPix == n)
					s++;
			}

			
		}

		// 小于或大于阈值的区域,赋以与背景一样的颜色,进行消去
		if((s <= nMinArea)||(s > nMaxArea))
		{			
			for (j = 0; j < lHeight - 1; j++)
			{
				for(i = 0; i < lWidth - 1; i++)
				{
					nBlackPix =pnBinary[lLineBytes * j + i + 1];
				
					if(nBlackPix == n)
					{
						pnBinary[lLineBytes * j + i + 1] = 0;
					}			

				}
			}

		}

	}

	// 存储象素值,输出
	for(j = 0; j < lHeight; j++)
	{
		// 列
		for(i = 0; i < lWidth; i++)
		{
			// 二值图象
		    temp = pnBinary[j * lLineBytes + i] ;
			
			// 指向位图i行j列象素的指针
			lpSrc = (unsigned char*)lpDIBBits + lLineBytes * j + i;
			
			// 更新源图像
			if(temp != 0)
				* (lpSrc) = 0;
			else
				* (lpSrc) = 255;
		}
	}

	delete pnBinary;

	return true;
}